package net.simpleframework.swing;

import java.awt.event.ActionEvent;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

import net.simpleframework.util.LocaleI18n;
import net.simpleframework.util.StringUtils;

/**
 * 这是一个开源的软件，请在LGPLv3下合法使用、修改或重新发布。
 * 
 * @author 陈侃(cknet@126.com, 13910090885)
 *         http://code.google.com/p/simpleframework/
 *         http://www.simpleframework.net
 */
public abstract class JActions {
	public static abstract class ActionCallback {
		public boolean executeInQueue() {
			return false;
		}

		private EventObject eventObject;

		public EventObject getEventObject() {
			return eventObject;
		}

		public void setEventObject(final EventObject eventObject) {
			this.eventObject = eventObject;
		}

		public abstract void doAction();
	}

	static void doActionCallback(final JComponent component, final ActionCallback callback) {
		if (callback == null) {
			return;
		}
		final Runnable r = new Runnable() {
			@Override
			public void run() {
				SwingUtils.setWaitCursor(component);
				if (component instanceof JAbstractTableEx) {
					SwingUtils.setWaitCursor(((JAbstractTableEx) component).getTableHeader());
					final JAbstractTableEx t1 = ((JAbstractTableEx) component).getOppositeTable();
					if (t1 != null) {
						SwingUtils.setWaitCursor(t1);
						SwingUtils.setWaitCursor(t1.getTableHeader());
					}
				}
				try {
					callback.doAction();
				} catch (final Exception ex) {
					SwingUtils.showError(SwingUtils.findWindow(component), ex);
				} finally {
					SwingUtils.setDefaultCursor(component);
					if (component instanceof JAbstractTableEx) {
						SwingUtils.setDefaultCursor(((JAbstractTableEx) component).getTableHeader());
						final JAbstractTableEx t1 = ((JAbstractTableEx) component).getOppositeTable();
						if (t1 != null) {
							SwingUtils.setDefaultCursor(t1);
							SwingUtils.setDefaultCursor(t1.getTableHeader());
						}
					}
				}
			}
		};

		if (callback.executeInQueue()) {
			SwingUtilities.invokeLater(r);
		} else {
			new SwingWorker<Object, Object>() {
				@Override
				protected Object doInBackground() throws Exception {
					synchronized (getLock(component)) {
						r.run();
					}
					return null;
				}
			}.execute();
		}
	}

	private static Map<JComponent, Object> worker;

	private static synchronized Object getLock(final JComponent component) {
		if (worker == null) {
			worker = new HashMap<JComponent, Object>();
		}
		Object lock = worker.get(component);
		if (lock == null) {
			worker.put(component, lock = new Object());
		}
		return lock;
	}

	static AbstractAction getAction(final JComponent component, final String name,
			final String icon, final ActionCallback actionCallback) {
		return new AbstractAction() {
			private static final long serialVersionUID = 8358539699561144749L;

			{
				if (StringUtils.hasText(name)) {
					putValue(Action.NAME, LocaleI18n.replaceI18n(name));
				}
				if (StringUtils.hasText(icon)) {
					putValue(Action.SMALL_ICON, SwingUtils.loadIcon(icon));
				}
			}

			@Override
			public void actionPerformed(final ActionEvent e) {
				actionCallback.setEventObject(e);
				doActionCallback(component, actionCallback);
			}
		};
	}
}
